Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

recursive rm | wildcards | common file extension

2 views
Skip to first unread message

evan....@nospamcornell.edu

unread,
Nov 15, 2002, 5:37:52 PM11/15/02
to
Suppose I have a set of files, all with a common extension (say,
abc), distributed over several directories. I want to delete them
all, non-interactively, with a single command.

The obvious thing to try

rm -r *.abc

doesn't do it. Is there an easy way to do recursive file deletes for
files with a common extension? If there is, I'd love to know...

Thanks!

Chris F.A. Johnson

unread,
Nov 15, 2002, 5:54:07 PM11/15/02
to

find . -name '*.abc' -print0 | xargs -0 rm

--
Chris F.A. Johnson http://cfaj.freeshell.org
===================================================================
My code (if any) in this post is copyright 2002, Chris F.A. Johnson
and may be copied under the terms of the GNU General Public License

Michael Heiming

unread,
Nov 15, 2002, 6:43:49 PM11/15/02
to
evan....@NOSPAMcornell.edu wrote:

find . -type f -name "*.abc" -exec rm {} \;

Hint:
man find

Michael Heiming
--
Remove +SIGNS, if you expect an answer

Michael Slass

unread,
Nov 15, 2002, 6:54:27 PM11/15/02
to
Michael Heiming <michael...@heiming.de> writes:

>
>find . -type f -name "*.abc" -exec rm {} \;
>
>Hint:
>man find


Don't go blindly executing this one before you understand what it
does. I would read the man page first, and then run find with the
-print switch (rather than the -exec ...) to see what files it's going
to find.

Also, you'll probably (depending on your shell) need to escape or
quote the curly braces.

--
Mike Slass

Michael Heiming

unread,
Nov 15, 2002, 8:04:17 PM11/15/02
to
Michael Slass wrote:

> Michael Heiming <michael...@heiming.de> writes:
>
>>
>>find . -type f -name "*.abc" -exec rm {} \;
>>
>>Hint:
>>man find
>
>
> Don't go blindly executing this one before you understand what it
> does. I would read the man page first, and then run find with the
> -print switch (rather than the -exec ...) to see what files it's going
> to find.

Good advice.

> Also, you'll probably (depending on your shell) need to escape or
> quote the curly braces.

Presuming bash, no need.

John Hunter

unread,
Nov 15, 2002, 8:33:17 PM11/15/02
to
>>>>> "Michael" == Michael Heiming <michael...@heiming.de> writes:

Michael> find . -type f -name "*.abc" -exec rm {} \;

Depending on the number of files you exppect to find, you might get
better performance out of

rm `find . -name "*.abc"`

If the arg list is too long for rm to handle, go with the first
version, otherwise, the backtick operator version should run faster
because rm needs to be spawned only once.


John Hunter

Joseph William Dixon

unread,
Nov 16, 2002, 12:21:04 AM11/16/02
to
On Sat, 16 Nov 2002, Michael Heiming wrote:
> > The obvious thing to try
> >
> > rm -r *.abc
> >
> > doesn't do it. Is there an easy way to do recursive file deletes for
> > files with a common extension? If there is, I'd love to know...
>
> find . -type f -name "*.abc" -exec rm {} \;
>
> Hint:
> man find

Reading it now, for the 3rd or 4th time. Horrible, horrible, horrible.
How anyone ever figured out how to use that thing is beyond me...

--
"...there are hardly any excesses of the most crazed psychopath that cannot
easily be duplicated by a normal, kindly family man who just comes into
work every day and has a job to do." [Terry Pratchett, "Small Gods"]
http://www.chebucto.ns.ca/~aa343/index.html

evan....@nospamcornell.edu

unread,
Nov 16, 2002, 9:17:53 AM11/16/02
to
On Sat, 16 Nov 2002 01:21:04 -0400, Joseph William Dixon
<aa...@chebucto.ns.ca> wrote:

>On Sat, 16 Nov 2002, Michael Heiming wrote:
>> > The obvious thing to try
>> >
>> > rm -r *.abc
>> >
>> > doesn't do it. Is there an easy way to do recursive file deletes for
>> > files with a common extension? If there is, I'd love to know...
>>
>> find . -type f -name "*.abc" -exec rm {} \;
>>
>> Hint:
>> man find
>
> Reading it now, for the 3rd or 4th time. Horrible, horrible, horrible.
>How anyone ever figured out how to use that thing is beyond me...
>

They don't - the look on this newsgroup first. :-)


Thanks all. Put the following in a shell script (which I call rm_rec),
to which I pass the wildcard argument:

find . -type f -name $1 -exec rm {} \;

Seems to work fine. So, rm_rec *.abc does just what I want it to.

Thanks!

Michael Heiming

unread,
Nov 16, 2002, 9:55:24 AM11/16/02
to
Joseph William Dixon wrote:

> On Sat, 16 Nov 2002, Michael Heiming wrote:

[..]


>> find . -type f -name "*.abc" -exec rm {} \;
>>
>> Hint:
>> man find
>
> Reading it now, for the 3rd or 4th time. Horrible, horrible,
> horrible.
> How anyone ever figured out how to use that thing is beyond me...

Horrible?

$ find --help
Usage: find [path...] [expression]
default path is the current directory; default expression is -print
expression may consist of:
operators (decreasing precedence; -and is implicit where no others are
given):
( EXPR ) ! EXPR -not EXPR EXPR1 -a EXPR2 EXPR1 -and EXPR2
EXPR1 -o EXPR2 EXPR1 -or EXPR2 EXPR1 , EXPR2
options (always true): -daystart -depth -follow --help
-maxdepth LEVELS -mindepth LEVELS -mount -noleaf --version -xdev
tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N
-cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group
NAME
-ilname PATTERN -iname PATTERN -inum N -ipath PATTERN -iregex
PATTERN
-links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE
-nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN
-size N[bckw] -true -type [bcdpfls] -uid N -used N -user NAME
-xtype [bcdpfls]

actions: -exec COMMAND ; -fprint FILE -fprint0 FILE -fprintf FILE FORMAT
-ok COMMAND ; -print -print0 -printf FORMAT -prune -ls
[..]

It's more or less self-explanatory and it has a good man page, sure one
needs to actually read it and play around, put in "echo" in "-exec"
statements, to see what they do and be really sure you know what you
are doing, case you are running "-exec rm -rf {}" as root;)

Paul Kimoto

unread,
Nov 16, 2002, 10:59:08 AM11/16/02
to
In article
<Pine.GSO.3.95.iB1.0.102...@halifax.chebucto.ns.ca>,

Joseph William Dixon wrote:
> On Sat, 16 Nov 2002, Michael Heiming wrote:
>> Hint:
>> man find

> Reading it now, for the 3rd or 4th time. Horrible, horrible, horrible.
> How anyone ever figured out how to use that thing is beyond me...

You (like me) may prefer the findutils info pages.

--
Paul Kimoto
This message was originally posted on Usenet in plain text. Any images,
hyperlinks, or the like shown here have been added without my consent,
and may be a violation of international copyright law.

Paul Lutus

unread,
Nov 16, 2002, 12:24:33 PM11/16/02
to
On Sat, 16 Nov 2002 14:17:53 +0000, evan.cooc wrote:

/ ...

> Thanks all. Put the following in a shell script (which I call rm_rec),
> to which I pass the wildcard argument:
>
> find . -type f -name $1 -exec rm {} \;

There is a very serious problem with this script. As written, the $1 above
will be expanded by the shell, using the filenames in the current
directory. For recursion to work as expected, you must do it this way:

find . -type f -name "$1" -exec rm {} \;

> Seems to work fine. So, rm_rec *.abc does just what I want it to.

No, in fact it does not. To see why it doesn't work, type this into a
shell using different test directories:

# echo *.abc

In a directory that has no *.abc candidate files, the expansion doesn't
happen and the script functions as intended. But in a directory that
itself contains *.abc files, the search string is expanded, which prevents
your script from working.

Also, for a script corrected as described, you cannot call the script
using a bare wildcard argument, for the same reason. You must say:

# scriptname "*.abc"

Review the thread. Did you notice the people who offered this solution for
you, quoted their wilcard arguments?

--
Paul Lutus
www.arachnoid.com

Andrew

unread,
Nov 16, 2002, 12:39:53 PM11/16/02
to
On Sat, 16 Nov 2002 09:24:33 -0800, "Paul Lutus" <nos...@nosite.zzz>
wrote:

*Note, I would not listen to the above crap. It's peppered with
errors, small errors.


Andrew
www.wbglinks.net

Richard Pitt

unread,
Nov 16, 2002, 2:44:31 PM11/16/02
to

I use
find . -name "*.abc" -print | xargs rm -f

the "-print" is optional with most versions of find today - they do it by
default - but I'm from the old school and need stuff to work on old SCO
systems and such so got into the habit of putting it in anyway.

The xargs command takes a chunk of output from the pipe and passes it as
command line args to the rm -f command which short circuits the need to
guess whether or not the number of found files will exceed maxargs.

the -f fixes problems where a directory might have that name (unless you
want to delete it recursively too in which case you might put in -r
instead)

richard

--
Richard C. Pitt C.E.O. Belcarra Technologies
ric...@belcarra.com direct: 604-644-9265 www.belcarra.com
Software Systems - design and implementation: Internet, Linux, Communications
USB, RNDIS, ATM, E-mail, SQL, Encryption, Security, Web, Embedded Systems

John Hunter

unread,
Nov 16, 2002, 2:52:02 PM11/16/02
to
>>>>> "Richard" == Richard Pitt <ric...@belcarra.com> writes:

Richard> The xargs command takes a chunk of output from the pipe
Richard> and passes it as command line args to the rm -f command
Richard> which short circuits the need to guess whether or not the
Richard> number of found files will exceed maxargs.

Thanks for the explanation. I've always know about xargs but not how
to use it. It sounds like the best of both worlds -- it handles long
lists of arguments like -exec without the inefficiencies of spawning so
many processes.

Gotta love the old UNIX gurus who conceived of all this stuff.

John Hunter

Hansjoerg Lipp

unread,
Nov 16, 2002, 3:09:11 PM11/16/02
to
Richard Pitt wrote:

> I use
> find . -name "*.abc" -print | xargs rm -f

You should use

find . -name "*.abc" -print0 | xargs -0 rm -f

to prevent that file names with spaces are interpreted as several files
by the xargs command.

Chris F.A. Johnson

unread,
Nov 16, 2002, 3:24:29 PM11/16/02
to
In article <ln0dtu41jsufaiogp...@4ax.com>, Andrew wrote:
[snip]

>
> *Note, I would not listen to the above crap. It's peppered with
> errors, small errors.

Which you are unable to identify? Or are you just not interested
in being helpful?

**PLONK**

Frank da Cruz

unread,
Nov 16, 2002, 3:43:33 PM11/16/02
to
In article <ar68n0$4g3$1...@news.uni-stuttgart.de>,
Hansjoerg Lipp <hjl...@web.de> wrote:
:
As noted, you can delete files recursively using find, xargs, and rm --
three programs, whose syntax and interactions might vary from one Unix
version to another, and as you can see from this discussion, the details
and quoting rules can be confusing. The same thing can be done in a more
straightforward way at the C-Kermit> prompt:

delete /recursive *.abc

Plus you get a lot more options for selecting which files to delete:

C-Kermit>delete ? File specification; or switch, one of the following:

/after: /except: /nodotfiles /not-before: /summary
/ask /heading /noheading /page /tree
/before: /larger-than: /nolist /recursive /type:
/directories /list /nopage /simulate
/dotfiles /noask /not-after: /smaller-than:

C-Kermit>delete

Dates, sizes, etc; whether to include or exclude dot files and directory
files; exception lists; optional interactive prompting; various listing
options. Of particular interest is a simulation mode, allowing you to see
which files WOULD be deleted without actually deleting them. Another
unique feature is the /TYPE:{TEXT,BINARY,ALL} option, which lets you pick
only text files or only binary files for deletion (in addition to your
other criteria). C-Kermit is here:

http://www.columbia.edu/kermit/ckermit.html

- Frank

Lee Sau Dan

unread,
Nov 19, 2002, 3:17:15 AM11/19/02
to
>>>>> "Paul" == Paul Lutus <nos...@nosite.zzz> writes:

Paul> No, in fact it does not. To see why it doesn't work, type
Paul> this into a shell using different test directories:

Paul> # echo *.abc

Paul> In a directory that has no *.abc candidate files, the
Paul> expansion doesn't happen and the script functions as
Paul> intended.

Just for bash/sh. In csh, the shell will complain about the
non-matching pattern. (This is one aspect of the csh that I like.
But I hate csh and its broken, C-pretending syntax in general.) That
explains why I always quote the pattern when using "find -name
'*.abc'", whereas I have observed some others, who have only had bash
experience, type "find -name *.abc".

--
Lee Sau Dan 李守敦(Big5) ~{@nJX6X~}(HZ)

E-mail: dan...@informatik.uni-freiburg.de
Home page: http://www.informatik.uni-freiburg.de/~danlee

Lee Sau Dan

unread,
Nov 19, 2002, 3:11:26 AM11/19/02
to
>>>>> "Richard" == Richard Pitt <ric...@belcarra.com> writes:

Richard> I use find . -name "*.abc" -print | xargs rm -f

Richard> the "-print" is optional with most versions of find today

Only for GNU find. Try it on Solaris, AIX, etc.

Another reason that I find GNU softwares more "user-friendly". The
defaults always tend to be more reasonable than the proprietary
implementations. (Also 'ifconfig' and 'route' on Linux, as compared
to, e.g., AIX.)

Lee Sau Dan

unread,
Nov 19, 2002, 3:09:39 AM11/19/02
to
>>>>> "John" == John Hunter <jdhu...@nitace.bsd.uchicago.edu> writes:

>>>>> "Michael" == Michael Heiming <michael...@heiming.de> writes:

Michael> find . -type f -name "*.abc" -exec rm {} \;

John> Depending on the number of files you exppect to find, you
John> might get better performance out of

John> rm `find . -name "*.abc"`

John> If the arg list is too long for rm to handle, go with the
John> first version, otherwise, the backtick operator version
John> should run faster because rm needs to be spawned only once.

man xargs

Dave Brown

unread,
Nov 19, 2002, 2:47:07 PM11/19/02
to
In article <m3ptt25...@mika.informatik.uni-freiburg.de>, Lee Sau Dan wrote:
>>> "Richard" == Richard Pitt <ric...@belcarra.com> writes:
>
> Richard> I use find . -name "*.abc" -print | xargs rm -f
>
> Richard> the "-print" is optional with most versions of find today
>
> Only for GNU find. Try it on Solaris, AIX, etc.
> ...

"-print" unneeded on AIX (after v 3.2, 5.1 is current.) According to
online Solaris 8 manpage, "-print" is unneeded. (I don't use Solaris
so I can't say when it bacame so.)

--
Dave Brown Austin, TX

evan....@nospamcornell.edu

unread,
Nov 19, 2002, 1:18:19 PM11/19/02
to
On Sat, 16 Nov 2002 09:24:33 -0800, "Paul Lutus" <nos...@nosite.zzz>
wrote:

>On Sat, 16 Nov 2002 14:17:53 +0000, evan.cooc wrote:


>
>/ ...
>
>> Thanks all. Put the following in a shell script (which I call rm_rec),
>> to which I pass the wildcard argument:
>>
>> find . -type f -name $1 -exec rm {} \;
>
>There is a very serious problem with this script. As written, the $1 above
>will be expanded by the shell, using the filenames in the current
>directory. For recursion to work as expected, you must do it this way:
>
>find . -type f -name "$1" -exec rm {} \;
>
>> Seems to work fine. So, rm_rec *.abc does just what I want it to.
>
>No, in fact it does not. To see why it doesn't work, type this into a
>shell using different test directories:
>
># echo *.abc
>
>In a directory that has no *.abc candidate files, the expansion doesn't
>happen and the script functions as intended. But in a directory that
>itself contains *.abc files, the search string is expanded, which prevents
>your script from working.
>
>Also, for a script corrected as described, you cannot call the script
>using a bare wildcard argument, for the same reason. You must say:
>
># scriptname "*.abc"
>

Interesting - but typo on my part. I would type

rm_rec "*.abc", and it DOES work as described.


evan....@nospamcornell.edu

unread,
Nov 19, 2002, 1:19:57 PM11/19/02
to
Remembering, of course, that you can either (i) pass a quited argument
to the script, or (ii) have the script assume the argument is
unquoted, and quote it for you.

You say 'tomatoe', I say 'tomahto'.


Paul Lutus

unread,
Nov 19, 2002, 3:59:00 PM11/19/02
to
On Tue, 19 Nov 2002 18:18:19 +0000, evan.cooc wrote:

/ ...

> Interesting - but typo on my part. I would type


>
> rm_rec "*.abc", and it DOES work as described.

You are not listening. If there are no files that match *.abc in the
current directory, your script will work as expected.

If there *are* files that match *.abc in the current directory, your
script will *not* work as expected.

Try it! Create a file in the current directory with the approproate
suffix:

# touch xxx.abc

Then run your script. If the argument inside the script is not quoted as I
explained, it will fail.

WRONG: find . -type f -name $1 -exec rm {} \;

RIGHT: find . -type f -name "$1" -exec rm {} \;

This is because the shell expands $1 when it encounters it, based on the
contents of the current directory, but it does not expand "$1".

# echo *.abc

xxx.abc

# echo "*.abc"

*.abc

Got it? You must quote the argument twice -- first when you write the
shell script, and again when you invoke it.

--
Paul Lutus
www.arachnoid.com

Paul Lutus

unread,
Nov 19, 2002, 4:08:14 PM11/19/02
to
On Tue, 19 Nov 2002 18:19:57 +0000, evan.cooc wrote:

> Remembering, of course, that you can either (i) pass a quited argument
> to the script, or (ii) have the script assume the argument is unquoted,
> and quote it for you.

False. You must do both. Imagine "evidence." Picture "evidence" in your
mind. Imagine being a scientist, or having any scientific training. If
this thought makes you dizzy, sit down.

> You say 'tomatoe', I say 'tomahto'.

No, you must do both. DO you own a computer? Can you type?

Create this script:

***********************

#!/bin/sh

echo $1

***********************

Call it "try.sh". Make it executable. Now create a file to match the
wildcard argument:

# touch xxx.abc.

Now do this:

# chmod +x try.sh

# ./try.sh *.abc
xxx.abc

# ./try.sh "*.abc"
xxx.abc

Gee, that's funny! IT DIDN'T WORK! SOMETHING MUST BE WRONG!

Now edit your shell script like this:

echo "$1"

Then test it:

# ./try.sh *.abc
xxx.abc

# ./try.sh "*.abc"
*.abc

What can we conclude from this scientific experiment? YOU MUST QUOTE BOTH
THE SHELL'S ARGUMENT AND THE COMMAND-LINE ARGUMENT. NOT JUST ONE, NOT
JUST THE OTHER. BOTH OF THEM.

--
Paul Lutus
www.arachnoid.com

Lee Sau Dan

unread,
Nov 20, 2002, 8:49:38 AM11/20/02
to
>>>>> "Dave" == Dave Brown <dhb...@hobbes.dhbrown.net> writes:

Richard> the "-print" is optional with most versions of find today
>> Only for GNU find. Try it on Solaris, AIX, etc. ...

Dave> "-print" unneeded on AIX (after v 3.2, 5.1 is current.)
Dave> According to online Solaris 8 manpage, "-print" is
Dave> unneeded. (I don't use Solaris so I can't say when it bacame
Dave> so.)

Maybe, the changed it in later versions of Solaris. Back to the dates
when it was still SunOS, 'find' would complain if no predicates are
specified at all.

0 new messages